---@class DamageManager
DamageManager = ClientFight.CreateClass("DamageManager")
local this = DamageManager

--[[
* 攻击
*
* @param target
* @param triggerFrame 触发帧数
]]
function this.attack(skill, target, triggerFrame, skillUniqueId)
    local skillEffect = SkillManager.getSkillEffect(skill.skill.skillBean.f_SkillScript);
    if (skillEffect ~= nil) then
        if (skillEffect:attack(skill, target)) then
            return false;
        end
    end

    -- 目标已经死亡
    if (target:isDie()) then
        return false;
    end

    local fight = skill.fight;
    local fighter = skill.fighter;
    local skillBean = skill.skill.skillBean;

    local hurtBase = 0;
    if (skillBean.f_HurtBase ~= nil) then
        hurtBase = skillBean.f_HurtBase[1];
    end
    local hurtCorrectFactor = 10000;
    if (skillBean.f_HurtCorrectFactor ~= nil) then
        hurtCorrectFactor = skillBean.f_HurtCorrectFactor[1];
    end

    -- 是否命中目标
    local hit;
    local result = this.damage(skill, target, hurtBase, hurtCorrectFactor, triggerFrame, skillUniqueId);

    hit = (result.state ~= DamageResultTypeEnum.DODGE);

    if (skillEffect ~= nil) then
        skillEffect:damageAfter(skill, target, result);
    end

    local ours = nil;
    local others = nil;

    --为了避免重复触发死亡事件用这个来标记
    local targetDie = false;

    SkillRoleMgr.savePathFile(string.format("[%s][HP]死亡前-目标%s当前血量%s,死亡状态%s", fight.frame, target.fighterId, target.hp, target.dieStatus));
    if (target:isDie() and not target.dieStatus) then
        -- 触发死亡前事件
        EventManager.notifyEventListener(fight, FightEventEnum.BEFORE_TARGET_DIE, fighter.fighterId, target, skill, result, false);
        -- 触发死亡前事件
        EventManager.notifyEventListener(fight, FightEventEnum.BEFORE_OURSELF_DIE, target.fighterId, fighter, skill, result, false);

        ours = FighterUtils.getOursBy(target, true, nil);
        for i, _fighter in pairs(ours) do

            EventManager.notifyEventListener(fight, FightEventEnum.ANY_FIGHTER_DIE_BEFORE, _fighter.fighterId, target, skill, result, true);
            EventManager.notifyEventListener(fight, FightEventEnum.OUR_FIGHTER_DIE_BEFORE, _fighter.fighterId, target, skill, result, true);
        end

        others = FighterUtils.getOthersBy(target, true, nil);
        for i, _fighter in pairs(others) do

            EventManager.notifyEventListener(fight, FightEventEnum.ANY_FIGHTER_DIE_BEFORE, _fighter.fighterId, target, skill, result, true);
            EventManager.notifyEventListener(fight, FightEventEnum.OTHER_FIGHTER_DIE_BEFORE, _fighter.fighterId, target, skill, result, true);
        end
    elseif (target.usingSkill ~= nil) then
        if (FighterStateEnum.is(target, FighterStateEnum.CAN_NOT_USE_SKILL) and target.usingSkill.skill.skillBean.f_SkillType ~= SkillTypeEnum.NORMAL_ATTACK) then
            SkillRoleMgr.savePathFile(string.format("[%s][SKILL]%s的技能%s因为不可释放技能而进入结束逻辑", fight.frame, target.fighterId, target.usingSkill.skill.skillBean.f_SkillID));
            SkillManager.finishSkill(target.usingSkill, true, FinishSkillReasonEnum.CAN_NOT_USE_SKILL);
        elseif (FighterStateEnum.is(target, FighterStateEnum.CAN_NOT_NORMAL_ATTACK) and target.usingSkill.skill.skillBean.f_SkillType == SkillTypeEnum.NORMAL_ATTACK) then
            SkillRoleMgr.savePathFile(string.format("[%s][SKILL]%s的技能%s因为不可释普攻而进入结束逻辑", fight.frame, target.fighterId, target.usingSkill.skill.skillBean.f_SkillID));
            SkillManager.finishSkill(target.usingSkill, true, FinishSkillReasonEnum.CAN_NOT_USE_SKILL);
        end
    end

    SkillRoleMgr.savePathFile(string.format("[%s][HP]准备执行死亡逻辑 目标%s当前血量%s,死亡状态%s", fight.frame, target.fighterId, target.hp, target.dieStatus));
    if (target:isDie() and not target.dieStatus) then
        targetDie = true;
        FighterManager.die(fight, target, fighter, FighterDieType.NORMAL);
    end

    if (fighter:isDie() and not fighter.dieStatus) then
        FighterManager.die(fight, fighter, target, FighterDieType.NORMAL);
        -- 去除所有BUFF
        FighterManager.removeAllBuff(fight, fighter);
    elseif (fighter.usingSkill ~= nil) then
        if (FighterStateEnum.is(fighter, FighterStateEnum.CAN_NOT_USE_SKILL) and fighter.usingSkill.skill.skillBean.f_SkillType ~= SkillTypeEnum.NORMAL_ATTACK) then
            SkillManager.finishSkill(fighter.usingSkill, true, FinishSkillReasonEnum.CAN_NOT_USE_SKILL);
        elseif (FighterStateEnum.is(fighter, FighterStateEnum.CAN_NOT_NORMAL_ATTACK) and fighter.usingSkill.skill.skillBean.f_SkillType == SkillTypeEnum.NORMAL_ATTACK) then
            SkillManager.finishSkill(fighter.usingSkill, true, FinishSkillReasonEnum.CAN_NOT_USE_SKILL);
        end
    end

    if (fight.finish == 0 and target:isDie() and targetDie) then
        -- 触发死亡后事件
        EventManager.notifyEventListener(fight, FightEventEnum.AFTER_TARGET_DIE, fighter.fighterId, target, skill, result, false);
        -- 触发死亡后事件
        EventManager.notifyEventListener(fight, FightEventEnum.AFTER_OURSELF_DIE, target.fighterId, fighter, skill, result, false);

        ours = FighterUtils.getOursBy(target, true, nil);
        for i, _fighter in pairs(ours) do

            EventManager.notifyEventListener(fight, FightEventEnum.ANY_FIGHTER_DIE_AFTER, _fighter.fighterId, target, skill, result, true);
            EventManager.notifyEventListener(fight, FightEventEnum.OUR_FIGHTER_DIE_AFTER, _fighter.fighterId, target, skill, result, true);
        end

        others = FighterUtils.getOthersBy(target, true, nil);
        for i, _fighter in pairs(others) do

            EventManager.notifyEventListener(fight, FightEventEnum.ANY_FIGHTER_DIE_AFTER, _fighter.fighterId, target, skill, result, true);
            EventManager.notifyEventListener(fight, FightEventEnum.OTHER_FIGHTER_DIE_AFTER, _fighter.fighterId, target, skill, result, true);
        end
        -- 去除所有BUFF
        FighterManager.removeAllBuff(fight, target);
        if (skillEffect ~= nil) then
            skillEffect:killAfter(skill, target, result);
        end
    end
    SkillRoleMgr.savePathFile(string.format("[%s][HP]死亡后-目标%s当前血量%s,死亡状态%s", fight.frame, target.fighterId, target.hp, target.dieStatus));
    return hit;
end

--[[
* 对于特殊逻辑脚本中直接设置血量的,调用此方法,常规逻辑不走这个方法
* @param fighter 击杀者
* @param target 死亡者
]]


function this.checkAndDoDieWhenSetHp(fight, skill, fighter, target, result, triggerFrame)
    if (target:isDie() and not target.dieStatus) then
        -- 触发死亡前事件
        EventManager.notifyEventListener(fight, FightEventEnum.BEFORE_TARGET_DIE, fighter.fighterId, target, skill, result, false);
        -- 触发死亡前事件
        EventManager.notifyEventListener(fight, FightEventEnum.BEFORE_OURSELF_DIE, target.fighterId, fighter, skill, result, false);

        local ours = FighterUtils.getOursBy(target, true, nil);
        local others = FighterUtils.getOthersBy(target, true, nil);

        for i, _fighter in pairs(ours) do

            EventManager.notifyEventListener(fight, FightEventEnum.ANY_FIGHTER_DIE_BEFORE, _fighter.fighterId, target, skill, result, true);
            EventManager.notifyEventListener(fight, FightEventEnum.OUR_FIGHTER_DIE_BEFORE, _fighter.fighterId, target, skill, result, true);
        end

        for i, _fighter in pairs(others) do

            EventManager.notifyEventListener(fight, FightEventEnum.ANY_FIGHTER_DIE_BEFORE, _fighter.fighterId, target, skill, result, true);
            EventManager.notifyEventListener(fight, FightEventEnum.OTHER_FIGHTER_DIE_BEFORE, _fighter.fighterId, target, skill, result, true);
        end
    end
    local targetDie = false;
    if (target:isDie() and not target.dieStatus) then
        targetDie = true;
        FighterManager.die(fight, target, fighter, FighterDieType.NORMAL);
    end

    if (fight.finish == 0 and target:isDie() and targetDie) then

        -- 触发死亡后事件
        EventManager.notifyEventListener(fight, FightEventEnum.AFTER_TARGET_DIE, fighter.fighterId, target, skill, result, false);
        -- 触发死亡后事件
        EventManager.notifyEventListener(fight, FightEventEnum.AFTER_OURSELF_DIE, target.fighterId, fighter, skill, result, false);

        local ours = FighterUtils.getOursBy(target, true, nil);
        local others = FighterUtils.getOthersBy(target, true, nil);
        for i, _fighter in pairs(ours) do

            EventManager.notifyEventListener(fight, FightEventEnum.ANY_FIGHTER_DIE_AFTER, _fighter.fighterId, target, skill, result, true);
            EventManager.notifyEventListener(fight, FightEventEnum.OUR_FIGHTER_DIE_AFTER, _fighter.fighterId, target, skill, result, true);
        end

        for i, _fighter in pairs(others) do

            EventManager.notifyEventListener(fight, FightEventEnum.ANY_FIGHTER_DIE_AFTER, _fighter.fighterId, target, skill, result, true);
            EventManager.notifyEventListener(fight, FightEventEnum.OTHER_FIGHTER_DIE_AFTER, _fighter.fighterId, target, skill, result, true);
        end
        -- 去除所有BUFF
        FighterManager.removeAllBuff(fight, target);
    end
end

--[[
* 造成伤害处理完成造成伤害
*
* @param target
* @param triggerFrame 触发帧数
]]
function this.damage(skill, target, hurtBase, hurtCorrectFactor, triggerFrame, skillUniqueId)

    local fight = skill.fight;
    local fighter = skill.fighter;
    local skillBean = skill.skill.skillBean;

    -- 伤害前加buff
    local skillEffectActions = skill.actionFrames[triggerFrame];
    if skillUniqueId then
        for k, v in pairsByKeys(skill.actionUniqueId[skill.skillUniqueId]) do
            skillEffectActions = clone(skill.actionUniqueId[skillUniqueId][k]);
            skill.actionUniqueId[skill.skillUniqueId][k] = nil;
            break
        end
    end
    if (skillEffectActions ~= nil) then
        for i, action in pairs(skillEffectActions) do

            if (action.buffId > 0 and action.addType == BuffAddTrigger.DAMAGE_BEFORE) then
                BuffManager.addBuff(fight, skill, fighter, target, false, action.buffId, action.buffOverlay, target, skill);
            end
        end
    end


    -- 触发伤害计算前事件
    EventManager.notifyEventListener(fight, FightEventEnum.BEFORE_COUNT_DAMAGE, fighter.fighterId, target, skill, false, skillBean.f_HurtMethod);
    -- 触发被伤害计算前事件
    EventManager.notifyEventListener(fight, FightEventEnum.BEFORE_COUNT_BE_DAMAGE, target.fighterId, fighter, skill, false, skillBean.f_HurtMethod);

    local result = nil;
    if (skillBean.f_HurtMethod == SkillDamageTypeEnum.HEAL) then
        result = AttackUtils.calculateSkillHeal(skill, target);
    elseif (skillBean.f_HurtMethod == SkillDamageTypeEnum.NONE) then
        result = FightResult.New();
    else
        result = AttackUtils.calculateSkillDamage(skill, target);
    end
    result:setDamageType(skillBean.f_HurtMethod);
    SkillRoleMgr.savePathFile(string.format("[%s][SKILL]%s 对 %s 使用技能 %s 造成伤害 %s 伤害前hp %s", fight.frame, fighter.fighterId, target.fighterId, skillBean.f_SkillID, result.damage, target.hp));

    -- 触发伤害前事件
    EventManager.notifyEventListener(fight, FightEventEnum.BEFORE_DAMAGE, fighter.fighterId,
            target, skill, result, false);
    -- 触发被伤害前事件
    EventManager.notifyEventListener(fight, FightEventEnum.BEFORE_BE_DAMAGE, target.fighterId,
            fighter, skill, result, false);

    --召唤者伤害前事件
    local team = fight.teams[fighter.teamIndex];
    --        for (int i=0;i <team.fighters.size();i++ then
    --            Fighter f = team.fighters.get(i);
    --            if (f.summons and f.summonsCreater.fighterId == fighter.fighterId then
    --                EventManager.notifyEventListener(fight, FightEventEnum.SUMMONER_DAMAGE_BEFORE.getId(), f.fighterId,
    --                        target, skill, result, false, f.summonsCreater);
    --            }
    --        }
    local frameInfoCommand = ReportManager.hitToJsonString(fight, fighter, target, skillBean.f_SkillID, result.state, skill)
    FightManager.playActions(frameInfoCommand)
    table.insert(fight.actions, frameInfoCommand);

    local skillEffect = SkillManager.getSkillEffect(skill.skill.skillBean.f_SkillScript);
    if (skillEffect ~= nil) then
        if (skillEffect:damageBefore(skill, target, result)) then
            return result;
        end
    end
    local realDamage = 0;

    if (skillBean.f_HurtMethod == SkillDamageTypeEnum.HEAL) then
        realDamage = this.setFighterHp(fight, target, fighter, skill, result.state, result.damage, target.hp + result.damage, true, false, true);
    else
        if (result.damage > target.hp) then
            result.damage = target.hp;
        end
        realDamage = this.setFighterHp(fight, target, fighter, skill, result.state, -result.damage, target.hp - result.damage, true, false, true);
        if (result:isDamage()) then
            if (not result:isNO_ENERGY()) then
                local maxHp = FighterAttributeManager.getFightAttr(target, FighterAttributeEnum.HP);
                local rate = math.min(result.damage * Global.TEN_THOUSANDTH / maxHp / 100, 100);
                if (rate > 0) then
                    -- 增加能量
                    FighterManager.addEnergy(fight, target, skillBean.f_SkillID, skill.frame, Global.HURT_RECOVER_ENERGY * rate, EnergyChangeReasonEnum.DAMAGE);
                end
            end

            -- 吸血
            local suckBlood = countSuckBlood(fight, fighter, result);
            if (suckBlood > 0) then
                local suckFighter = fighter;
                if (fighter.summons and not fighter:isRealSummons()) then
                    suckFighter = fighter.summonsCreater;
                end
                if (suckFighter ~= nil and not suckFighter:isDie()) then
                    local beforHp = suckFighter.hp;
                    this.setFighterHp(fight, suckFighter, suckFighter, nil, result.state, suckBlood, suckFighter.hp + suckBlood, false, false, true);
                    SkillRoleMgr.savePathFile("[" .. fight.frame .. "][SKILL]" .. fighter.fighterId .. "对" .. target.fighterId .. "使用技能" .. skillBean.f_SkillID .. "吸血" .. suckBlood);
                    EventManager.notifyEventListener(fight, FightEventEnum.AFTER_SUCK_BLOOOD, suckFighter.fighterId, target, skill, result, false, skillBean.f_HurtMethod, suckBlood, beforHp);
                end
            end
        end
    end

    SkillRoleMgr.savePathFile(string.format("[%s][SKILL][%s]%s 对 %s 使用技能 %s 造成伤害处理完成 伤害后hp %s",
            fight.frame, skill.frame, fighter.fighterId, target.fighterId, skillBean.f_SkillID, target.hp));

    -- 触发伤害后事件
    EventManager.notifyEventListener(fight, FightEventEnum.AFTER_DAMAGE, fighter.fighterId, target, skill, result, false, skillBean.f_HurtMethod);
    -- 触发被伤害后事件
    EventManager.notifyEventListener(fight, FightEventEnum.AFTER_BE_DAMAGE, target.fighterId, fighter, skill, result, false, skillBean.f_HurtMethod);
    --召唤者伤害后事件
    --for i, f in pairs(fight.teams[fighter.teamIndex].fighters) do
    --
    --    if (f.summons and f.summonsCreater.fighterId == fighter.fighterId) then
    --        EventManager.notifyEventListener(fight, FightEventEnum.SUMMONER_DAMAGE_AFTER, f.fighterId,
    --                target, skill, result, false, f.summonsCreater);
    --    end
    --end

    -- 给受伤者友军发事件
    --local fighters = fight.teams[target.teamIndex].fighters;
    --for i, _fighter in pairs(fighters) do
    --
    --    if (not _fighter:isDie()) then
    --        EventManager.notifyEventListener(fight, FightEventEnum.AFTER_OURSELF_DAMAGE, _fighter.fighterId, target, skill, result, false, skillBean.f_HurtMethod);
    --    end
    --end

    -- 伤害后加buff
    if (skillEffectActions ~= nil) then
        for i, action in pairs(skillEffectActions) do
            if (action.buffId > 0) then
                if (action.addType == BuffAddTrigger.DAMAGE_AFTER and result:isDamage()) then
                    BuffManager.addBuff(fight, skill, fighter, target, false, action.buffId, action.buffOverlay, target, skill, result);
                elseif action.addType == BuffAddTrigger.DAMAGE_AFTER_2 and result.originalDamage > 0 then
                    BuffManager.addBuff(fight, skill, fighter, target, false, action.buffId, action.buffOverlay, target, skill, result);
                end
            end
        end
    end
    --if (skillBean.f_HurtMethod ~= SkillDamageTypeEnum.HEAL) then
    --    this.recordStatisticsValue(fighter, FightStatisticsEnum.ATTACK, result.damage);
    --end
    return result;
end

--[[
* 计算吸血
*
* @param fight
* @param fighter
* @param result
* @return
]]
function this.countSuckBlood(fight, fighter, result)
    if (FighterStateEnum.is(fighter, FighterStateEnum.BAN_SUCK_BLOOD)) then
        return 0;
    end

    -- 治疗伤害系数 * round( 目标生命值减少量 * 攻方吸血等级 * 吸血效果系数 * 最终治疗效果系数 )
    local blood = FighterAttributeManager.getFightAttr(fighter, FighterAttributeEnum.BLOOD);
    if (blood <= 0) then
        return 0;
    end
    local cure = FighterAttributeManager.getFightAttr(fighter, FighterAttributeEnum.CURE);
    --local curePer = FighterAttributeManager.getFightAttr(fighter, FighterAttributeEnum.CURE_PER);
    local cureEffect = FighterAttributeManager.getFightAttr(fighter, FighterAttributeEnum.CURE_EFFECT);
    if (cureEffect < -10000) then
        cureEffect = -10000;
    end
    --local suck = cure * math.round(result.damage * blood / Global.TEN_THOUSANDTH * curePer / Global.TEN_THOUSANDTH);
    local suck = cure * math.round(result.damage * blood / Global.TEN_THOUSANDTH);
    local cureEffectAdd = suck * cureEffect / 10000;
    suck = suck + cureEffectAdd;
    SkillRoleMgr.savePathFile(string.format("[%s][SKILL]%s造成伤害计算吸血 治疗效果=%s,",
            fight.frame, fighter.fighterId, cureEffect));
    return suck;
end

--[[
* 真实伤害，不会触发任何buff
*
* @param fight
* @param fighter
* @param target
* @param damageType {@link SkillDamageTypeEnum}
]]
addOverload(this, "realDamage", function(fight, fighter, target, buffModelId, result, damageType)
    this.realDamage(fight, fighter, target, buffModelId, result, damageType, true);
end, "table", "table", "table", "number", "table", "number")
--[[
* 真实伤害，不会触发任何buff
*
* @param fight
* @param fighter
* @param target
* @param damageType {@link SkillDamageTypeEnum}
]]
addOverload(this, "realDamage", function(fight, fighter, target, buffModelId, result, damageType, hpChangeNotifyEvent)
    local skill = FightUsingSkill.New();
    skill.fight = fight;
    skill.fighter = fighter;
    skill.target = target;
    skill.parameters[FightConst.BUFF_MODEL_ID] = buffModelId;
    if (damageType == SkillDamageTypeEnum.HEAL) then
        skill.skill = SkillManager.createFightSkill(fight, FightConst.BUFF_HEAL_SKILL, fighter);
    else
        skill.skill = SkillManager.createFightSkill(fight, FightConst.BUFF_DAMAGE_SKILL, fighter);
    end
    result.damageType = damageType;
    -- 触发伤害前事件
    EventManager.notifyEventListener(fight, FightEventEnum.BEFORE_DAMAGE, fighter.fighterId, target, skill, result, true, damageType);
    -- 触发被伤害前事件
    EventManager.notifyEventListener(fight, FightEventEnum.BEFORE_BE_DAMAGE, target.fighterId, fighter, skill, result, true, damageType);
    local realDamage = 0;
    if (result:isDamage()) then
        SkillRoleMgr.savePathFile("[" .. fight.frame .. "][SKILL]" .. fighter.fighterId .. "对" .. target.fighterId .. "造成直接伤害" .. result.damage);

        if (damageType == SkillDamageTypeEnum.HEAL) then
            realDamage = this.setFighterHp(fight, target, fighter, skill, result.state, result.damage, target.hp + result.damage, true, false, hpChangeNotifyEvent);
        else
            if (result.damage > target.hp) then
                result.famage = target.hp;
            end
            realDamage = this.setFighterHp(fight, target, fighter, skill, result.state, -result.damage, target.hp - result.damage, true, false, hpChangeNotifyEvent);
            if (not result:isNO_ENERGY()) then
                local maxHp = FighterAttributeManager.getFightAttr(target, ClientFight.FighterAttributeEnum.HP);
                local rate = math.min(result.damage * Global.TEN_THOUSANDTH / maxHp / 100, 100);
                if (rate > 0) then
                    -- 增加能量
                    FighterManager.addEnergy(fight, target, 0, 0, Global.HURT_RECOVER_ENERGY * rate, EnergyChangeReasonEnum.DAMAGE);
                end
            end
            -- 吸血
            local suckBlood = countSuckBlood(fight, fighter, result);
            if (suckBlood > 0) then
                local suckFighter = fighter;
                if (fighter.summons and not fighter.isRealSummons()) then
                    suckFighter = fighter.summonsCreater;
                end
                if (suckFighter ~= nil and not suckFighter:isDie()) then
                    local beforHp = suckFighter.hp;
                    this.setFighterHp(fight, suckFighter, suckFighter, skill, result.state, suckBlood, suckFighter.hp + suckBlood, false, false, hpChangeNotifyEvent);
                    EventManager.notifyEventListener(fight, FightEventEnum.AFTER_SUCK_BLOOOD, suckFighter.fighterId, target, skill, result, true, damageType, suckBlood, beforHp);
                end
            end
        end
    end

    -- 触发伤害后事件
    EventManager.notifyEventListener(fight, FightEventEnum.AFTER_DAMAGE, fighter.fighterId, target, skill, result, true, damageType);
    -- 触发被伤害后事件
    EventManager.notifyEventListener(fight, FightEventEnum.AFTER_BE_DAMAGE, target.fighterId, fighter, skill, result, true, damageType);
    --召唤者伤害后事件
    --for i, f in pairs(fight.teams[fighter.teamIndex].fighters) do
    --
    --    if (f.summons and f.summonsCreater.fighterId == fighter.fighterId) then
    --        EventManager.notifyEventListener(fight, FightEventEnum.SUMMONER_DAMAGE_AFTER, f.fighterId,
    --                target, skill, result, false, f.summonsCreater);
    --    end
    --end
    --
    --if (damageType ~= SkillDamageTypeEnum.HEAL) then
    --    this.recordStatisticsValue(fighter, FightStatisticsEnum.ATTACK, result.damage);
    --end

    if (target:isDie() and not target.dieStatus) then
        -- 触发死亡前事件
        EventManager.notifyEventListener(fight, FightEventEnum.BEFORE_TARGET_DIE, fighter.fighterId, target, skill, result, true);
        -- 触发死亡前事件
        EventManager.notifyEventListener(fight, FightEventEnum.BEFORE_OURSELF_DIE, target.fighterId, fighter, skill, result, true);

        local ours = FighterUtils.getOursBy(target, true, nil);
        for i, _fighter in pairs(ours) do

            EventManager.notifyEventListener(fight, FightEventEnum.ANY_FIGHTER_DIE_BEFORE, _fighter.fighterId, target, skill, result, true);
            EventManager.notifyEventListener(fight, FightEventEnum.OUR_FIGHTER_DIE_BEFORE, _fighter.fighterId, target, skill, result, true);
        end

        local others = FighterUtils.getOthersBy(target, true, nil);
        for i, _fighter in pairs(others) do

            EventManager.notifyEventListener(fight, FightEventEnum.ANY_FIGHTER_DIE_BEFORE, _fighter.fighterId, target, skill, result, true);
            EventManager.notifyEventListener(fight, FightEventEnum.OTHER_FIGHTER_DIE_BEFORE, _fighter.fighterId, target, skill, result, true);
        end
    end
    if (fighter:isDie() and not fighter.dieStatus) then
        FighterManager.die(fight, fighter, target, FighterDieType.NORMAL);
        FighterManager.removeAllBuff(fight, fighter);
    end
    if (target:isDie() and not target.dieStatus) then
        FighterManager.die(fight, target, fighter, FighterDieType.NORMAL);
        if (fight.finish == 0) then
            -- 触发死亡后事件
            EventManager.notifyEventListener(fight, FightEventEnum.AFTER_TARGET_DIE, fighter.fighterId, target, skill, result, true);
            -- 触发死亡后事件
            EventManager.notifyEventListener(fight, FightEventEnum.AFTER_OURSELF_DIE, target.fighterId, fighter, skill, result, true);

            local ours = FighterUtils.getOursBy(target, true, nil);
            for i, _fighter in pairs(ours) do

                EventManager.notifyEventListener(fight, FightEventEnum.ANY_FIGHTER_DIE_AFTER, _fighter.fighterId, target, skill, result, true);
                EventManager.notifyEventListener(fight, FightEventEnum.OUR_FIGHTER_DIE_AFTER, _fighter.fighterId, target, skill, result, true);
            end

            local others = FighterUtils.getOthersBy(target, true, nil);
            for i, _fighter in pairs(others) do

                EventManager.notifyEventListener(fight, FightEventEnum.ANY_FIGHTER_DIE_AFTER, _fighter.fighterId, target, skill, result, true);
                EventManager.notifyEventListener(fight, FightEventEnum.OTHER_FIGHTER_DIE_AFTER, _fighter.fighterId, target, skill, result, true);
            end
            -- 去除所有BUFF
            FighterManager.removeAllBuff(fight, target);
        end
    end
end, "table", "table", "table", "number", "table", "number", "boolean")


--[[
* 统计战斗数值
]]
function this.recordStatisticsValue(fighter, statistics, value)
    if (value == 0) then
        return ;
    end
    local summonsCreater = fighter.summonsCreater;
    if (summonsCreater ~= nil) then
        this.recordStatisticsValue(summonsCreater, statistics, value);
        return ;
    end
    value = math.abs(value);
    local fighterStats = fighter.fighterStats;
    if FightStatisticsEnum.ATTACK == statistics then
        fighterStats.attack = fighterStats.attack + value;

    end
    if FightStatisticsEnum.DO_HEAL == statistics then
        fighterStats.heal = fighterStats.heal + value;

    end
    if FightStatisticsEnum.BE_INJURED == statistics then

        fighterStats.beInjured = fighterStats.beInjured + value;
    end
end

--[[
* 设置hp
*
* @param change      变更值 >0加血 <0扣血 这个参数只用于记录战斗数值
* @param record      是否记录数值变化
* @param finalHp     有些情况下只setHp而不记录变更数值 配合record使用
* @param fighter     受伤害者
* @param trigger     攻击者  谁给我加的血, 这个一定不要搞错了,因为给人加血时,有加成影响的,需要
* @param checkDie    由于有些技能和buff脚本直接设置hp  所以不会走checkDie 所以这里加个参数判断需不需要检查死亡
* @param damageState {@link DamageResultTypeEnum}
* @param notifyEvent 这个参数,控制是否需要触发回血后的事件, 一定要谨慎, 因为如果是该方法触发事件,事件里再调用该方法,如果都为true,就死循环了
* @param skill        -- FIXME: 2021/5/25 wangjunhui 这个字段有问题 即控制了是否漂字 也会影响到死亡逻辑 后面需要优化下 让我想想先
]]
addOverload(this, "setFighterHp", function(fight, fighter, trigger, skill, damageState,
                                           change, finalHp, record, checkDie, notifyEvent, checkWudi)
    if (fighter == nil) then
        return 0;
    end
    if (fighter.dieStatus) then
        return 0;
    end
    local maxHp = FighterAttributeManager.getFightAttr(fighter, FighterAttributeEnum.HP);
    if (checkWudi and change < 0) then
        if (FighterStateEnum.is(fighter, FighterStateEnum.IMMUNITY)) then
            damageState = DamageResultTypeEnum.IMMUNITY;
            change = 0;
            finalHp = fighter.hp;
        end
    end
    local skillId = 0;
    local skillFrame = 0;
    local skillUUID = 0;
    if (skill ~= nil) then
        skillId = skill.skill.skillBean.f_SkillID;
        skillFrame = skill.frame;
        skillUUID = skill.skillUniqueId;
    end

    local logSkillId = skillId;
    if (fighter ~= trigger and finalHp < fighter.hp) then
        if finalHp < 0 then
            finalHp = 0;
        end
        local damage = fighter.hp - math.abs(finalHp);
        local lockDamageAtrr = FighterAttributeManager.getFightAttr(fighter, FighterAttributeEnum.LOCK_DAMAGE);
        if lockDamageAtrr > 0 then
            local lockDamageLimit = Utils.calcRatio(maxHp, lockDamageAtrr);
            if lockDamageLimit > 0 and damage > lockDamageLimit then
                local logChange = damage;
                damage = lockDamageLimit;
                finalHp = fighter.hp - damage;
                change = -damage;
                SkillRoleMgr.savePathFile(string.format("[%s][HP]Fighter%s变更hp,skillId:%s, 锁定伤害上限%s, 原伤害%s", fight.frame, fighter.fighterId, logSkillId, lockDamageLimit, logChange));
            end
        end
    end
    if finalHp > fighter.hp and notifyEvent then
        local result = FightResult.New();
        result.damage = finalHp - fighter.hp;
        EventManager.notifyEventListener(fight, FightEventEnum.HP_ADD_BEFORE, fighter.fighterId, trigger, skillId, result);
        change = result.damage;
        finalHp = fighter.hp + change;
    end

    local value = change;
    if (value < 0) then
        local frameInfoCommand = {};
        if (skillId ~= 0 and skillId ~= 101 and skillId ~= 102) then
            frameInfoCommand = ReportManager.damageToJsonString(fight, trigger, fighter, skillId, skillFrame, damageState, -value, skillUUID, skill)
        else
            frameInfoCommand = ReportManager.realDamageToJsonString(fight, trigger, fighter, damageState, -value)
        end
        table.insert(fight.actions, frameInfoCommand);
        FightManager.playActions(frameInfoCommand)
        if (not trigger.summons and fighter ~= trigger) then
            fighter.lastDamageMe = trigger.fighterId;
        end
    elseif (value == 0) then
        if (damageState ~= DamageResultTypeEnum.NORMAL and damageState ~= DamageResultTypeEnum.HEAL
                and damageState ~= DamageResultTypeEnum.CRIT) then
            local frameInfoCommand = {};
            if (skillId ~= 0 and skillId ~= 101 and skillId ~= 102) then
                frameInfoCommand = ReportManager.damageToJsonString(fight, trigger, fighter, skillId, skillFrame, damageState, -value, skillUUID, skill);
            else
                frameInfoCommand = ReportManager.realDamageToJsonString(fight, trigger, fighter, damageState, -value)
            end
            FightManager.playActions(frameInfoCommand)
            table.insert(fight.actions, frameInfoCommand);

        end
    else
        local frameInfoCommand = {}
        if (skillId ~= 0 and skillId ~= 101 and skillId ~= 102) then
            frameInfoCommand = ReportManager.healToJsonString(fight, trigger, fighter, skillId, skillFrame, value, skillUUID);
        else
            frameInfoCommand = ReportManager.realHealToJsonString(fight, trigger, fighter, value);
        end
        FightManager.playActions(frameInfoCommand)
        table.insert(fight.actions, frameInfoCommand);
    end

    local originalHp = fighter.hp;
    fighter.hp = finalHp;

    if (fighter.hp > maxHp) then
        change = maxHp - originalHp;
        fighter.hp = maxHp;
        if (change < 0) then
            change = 0;
        end
    end
    if (fighter.hp <= 0) then
        change = -originalHp;
        fighter.hp = 0;
        if (change > 0) then
            change = 0;
        end
    end
    SkillRoleMgr.savePathFile(string.format("[%s][HP]Fighter%s变更hp,skillId:%s,当前血量%s,是否检查死亡", fight.frame, fighter.fighterId, logSkillId, fighter.hp, checkDie));
    if (checkDie) then
        --TODO: 2021/2/3 wangjunhui 这里先这么处理 后面改成外面传FightResult 还有 triggerFrame
        local result = FightResult.New();
        result.damage = -change;
        result.state = DamageResultTypeEnum.NORMAL;
        checkAndDoDieWhenSetHp(fight, skill, trigger, fighter, result, 0);
    end

    change = fighter.hp - originalHp;
    if (record) then
        if (change < 0) then
            this.recordStatisticsValue(fighter, FightStatisticsEnum.BE_INJURED, change);
            local fighterStats = fighter.fighterStats;
            table.insert(fighterStats.attackerMe, trigger.fighterId);
        elseif (change > 0) then
            this.recordStatisticsValue(trigger, FightStatisticsEnum.DO_HEAL, change);
        end
    end
    if (fighter ~= trigger and change < 0) then
        this.recordStatisticsValue(trigger, FightStatisticsEnum.ATTACK, -change);--/统计伤害
    end
    if (notifyEvent and change ~= 0) then
        if (change < 0) then
            EventManager.notifyEventListener(fight, FightEventEnum.HP_CHANGE_REDUCE, fighter.fighterId, -change);
        else
            EventManager.notifyEventListener(fight, FightEventEnum.HP_CHANGE_ADD, fighter.fighterId, change);
        end
        EventManager.notifyEventListener(fight, FightEventEnum.HP_CHANGE, fighter.fighterId, change);
    end
    return math.abs(change);
end, "table", "table", "table", "table", "number", "number", "number", "boolean", "boolean", "boolean", "boolean")

--[[
* 设置hp
*
* @param change      变更值 >0加血 <0扣血 这个参数只用于记录战斗数值
* @param record      是否记录数值变化
* @param finalHp     有些情况下只setHp而不记录变更数值 配合record使用
* @param fighter     受伤害者
* @param trigger     攻击者  谁给我加的血, 这个一定不要搞错了,因为给人加血时,有加成影响的,需要
* @param checkDie    由于有些技能和buff脚本直接设置hp  所以不会走checkDie 所以这里加个参数判断需不需要检查死亡
* @param damageState {@link DamageResultTypeEnum}
* @param notifyEvent 这个参数,控制是否需要触发回血后的事件, 一定要谨慎, 因为如果是该方法触发事件,事件里再调用该方法,如果都为true,就死循环了
* @param skill        -- FIXME: 2021/5/25 wangjunhui 这个字段有问题 即控制了是否漂字 也会影响到死亡逻辑 后面需要优化下 让我想想先
]]

addOverload(this, "setFighterHp", function(fight, fighter, trigger, skill, damageState, change, finalHp, record, checkDie, notifyEvent)
   return this.setFighterHp(fight, fighter, trigger, skill, damageState, change, finalHp, record, checkDie, notifyEvent, true);
end, "table", "table", "table", "table", "number", "number", "number", "boolean", "boolean", "boolean")

